package io.kiki.sba.registry.server.metadata.resource;

import io.kiki.sba.registry.common.model.GenericResponse;
import io.kiki.sba.registry.common.model.Node.NodeType;
import io.kiki.sba.registry.common.model.Response;
import io.kiki.sba.registry.common.model.metaserver.DataOperation;
import io.kiki.sba.registry.common.model.metaserver.blacklist.RegistryForbiddenServerRequest;
import io.kiki.sba.registry.server.metadata.lease.filter.RegistryForbiddenServerManager;
import io.kiki.sba.registry.server.metadata.resource.filter.LeaderAwareRestController;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import javax.ws.rs.*;
import javax.ws.rs.core.MediaType;


@Path("opsapi/v1")
public class RegistryCoreOpsResource {

    private final Logger logger = LoggerFactory.getLogger(RegistryCoreOpsResource.class);

    @Autowired
    private RegistryForbiddenServerManager registryForbiddenServerManager;

    @PUT
    @Path("/server/group/quit/{ip}")
    @Produces(MediaType.APPLICATION_JSON)
    @LeaderAwareRestController
    public Response kickoffServer(@FormParam(value = "cell") String cell, @FormParam(value = "nodeType") String nodeType, @PathParam(value = "ip") String ip) {
        logger.info("[kickoffServer][begin] server [{}][{}][{}]", cell, nodeType, ip);

        // first time deploy, session and data script not contains cell and app,
        // default return true, let shutdown trigger quit and join
        if (StringUtils.isBlank(cell) || StringUtils.isBlank(nodeType)) {
            return GenericResponse.buildSuccessResponse();
        }
        NodeType nodeTypeEnum = NodeType.codeOf(nodeType);
        if (nodeTypeEnum == null) {
            return GenericResponse.buildFailedResponse("invalid nodeType: " + nodeType);
        }

        if (StringUtils.isBlank(ip) //|| !IPAddressUtil.isIPv4LiteralAddress(ip)

        ) {
            logger.error("[kickoffServer]invalid ip: {}", ip);
            return GenericResponse.buildFailedResponse("invalid ip address: " + ip);
        }
        try {
            boolean success = registryForbiddenServerManager.addToBlacklist(new RegistryForbiddenServerRequest(DataOperation.add, nodeTypeEnum, ip, cell));

            if (!success) {
                logger.error("[kickoffServer] add ip: {} to blacklist fail.", ip);
            }
            return success ? GenericResponse.buildSuccessResponse() : GenericResponse.buildFailedResponse("kickoffServer: " + ip + " fail.");
        } catch (Throwable th) {
            logger.error("[kickoffServer]", th);
            return GenericResponse.buildFailedResponse(th.getMessage());
        } finally {
            logger.info("[kickoffServer][end] server [{}]", ip);
        }
    }

    @PUT
    @Path("/server/group/join/{ip}")
    @Produces(MediaType.APPLICATION_JSON)
    @LeaderAwareRestController
    public Response rejoinServerGroup(@FormParam(value = "cell") String cell, @FormParam(value = "nodeType") String nodeType, @PathParam(value = "ip") String ip) {
        logger.info("[rejoinServerGroup][begin] server [{}][{}][{}]", cell, nodeType, ip);

        // first time deploy, session and data script not contains cell and app,
        // default return true, let shutdown trigger quit and join
        if (StringUtils.isBlank(cell) || StringUtils.isBlank(nodeType)) {
            return GenericResponse.buildSuccessResponse();
        }
        NodeType nodeTypeEnum = NodeType.codeOf(nodeType);
        if (nodeType == null) {
            return GenericResponse.buildFailedResponse("invalid nodeType: " + nodeType);
        }

        if (StringUtils.isBlank(ip)// || !IPAddressUtil.isIPv4LiteralAddress(ip)
        ) {
            logger.error("[rejoinServerGroup]invalid ip: {}", ip);
            return GenericResponse.buildFailedResponse("invalid ip address: " + ip);
        }
        try {
            boolean success = registryForbiddenServerManager.removeFromBlacklist(new RegistryForbiddenServerRequest(DataOperation.remove, nodeTypeEnum, ip, cell));
            if (!success) {
                logger.error("[rejoinServerGroup] remove ip: {} to blacklist fail.", ip);
            }
            return success ? GenericResponse.buildSuccessResponse() : GenericResponse.buildFailedResponse("rejoinServerGroup: " + ip + " fail.");
        } catch (Throwable th) {
            logger.error("[rejoinServerGroup]", th);
            return GenericResponse.buildFailedResponse(th.getMessage());
        } finally {
            logger.info("[rejoinServerGroup][end] server [{}]", ip);
        }
    }


    protected RegistryCoreOpsResource setRegistryForbiddenServerManager(RegistryForbiddenServerManager registryForbiddenServerManager) {
        this.registryForbiddenServerManager = registryForbiddenServerManager;
        return this;
    }
}
